import { useChatStore } from "@/store/modules/chat";
import { getAiAnswer, getQuestionBankAi, getAnswerList } from "@/api/chat";
import config from "@/config/config.json";
import "@/utils/date.js";
const chatStore = useChatStore();
let timeout = null;
let typeObj = {
  prompt: "prompt",
};
let askTypeObj = {
  prompt: "prompt",
  custom: "custom",
};

/**
 * @class new一个ai问答，也包括题库问答
 * @property {String} apiType api类型，stream流式输出，normal非流式输出
 * @property {String} answerType 回答来源类型，ai是ai回答，questionBank是题库回答
 * @property {String} [question] 问题
 * @property {String} [apiUrl] 接口地址
 * @property {String} [fresh] 刷新方式，req：请求刷新，answerlikeanswerlike是找类似回答
 * @property {Boolean} [freshIsAi] 刷新是来自自己本身还是ai内容 为true就代表刷新是用ai的方式
 * @property {Object} [reqData] 接口请求参数

 * @function askQuestion 问答入口，new一个ai之后调用这个方法正式开始问ai
 */
export default class Ai {
  constructor(ai) {
    const {
      apiUrl,
      reqData,
      apiType = "stream",
      question,
      answerType,
      extraData,
      freshIsAi = true,
    } = ai;
    this.question = question;

    this.apiUrl = apiUrl;
    this.reqData = reqData; // 这个是接口自定义参数
    this.answerType = answerType; // ai/questionBank/aiQuestionBank题库伪造成ai/aiGuide:ai指令是通过
    this.apiType = apiType;
    this.answer = "";
    this.status = 0; // -2是表示终止
    this.isAnswer = false;
    this.freshIsAi = freshIsAi; // 刷新是否来自ai，白问百答本身内容来自题库，但是刷新来自ai
    this.requestTask = null;
    this.id = "";
    this.conversationId = "";
    this.extraData = extraData;
    this.time = new Date().Format("yyyy-MM-dd hh:mm:ss");
  }

  /**
   * @description 提问的入口文件
   * @param {*} req
   */
  askQuestion(req = {}) {
    // 添加问题
    // chatStore.addChat({
    //   content: this.question,
    // });
    this.isLoading = true;

    this.aiLoading();
    this.updateAnswer();
  }
  updateAnswer(req = {}) {
    let { apiType, answerType } = this;
    // 真ai，向ai问提示词
    if (apiType == "stream" && answerType == "ai") {
      this.getAiAnserFn(req);
    } else if (apiType == "stream" && answerType == "questionBank") {
      // 内容来自题库但是方式但是是流回答
      this.getQuestionBankAiAnswer(req);
    } else if (apiType == "normal" && answerType == "questionBank") {
      // 内容来自题库但是是普通显示（非流回答）
      this.getQuestionBankAnswer(req);
    }
  }
  freshAnswer(req) {
    chatStore.changeLoading(false);
    this.isLoading = true;
    if (this.freshIsAi) {
      this.getAiAnserFn(req);
    }
    this.updateAnswer();
  }

  aiLoading() {}
  startAnswer(req) {
    // 添加回复
    this.aiLoading();
    if (this.type == typeObj.prompt) {
      this.getAiAnserFn();
    } else if (this.answerType == "questionBank") {
      if (this.apiType == "normal") {
        this.getQuestionBankAnswer(req);
      } else if (this.apiType == "stream") {
        this.getQuestionBankAiAnswer(req);
      }
    }
    // chatStore.addChat({
    //   content: "ai回答啦",
    //   isAi: true,
    // });
  }
  stopAnswer() {
    console.log("ai类-requesttask-bort");
    this.isLoading = false;
    this.requestTask.abort();
    clearTimeout(timeout);
  }
  /**
   * @description 问ai，ai会流式回答（sse协议）
   * @param {*} req
   * @returns
   */
  getAiAnserFn(req = {}) {
    const chatModal = uni.getStorageSync("chatModal");
    let { question } = req;
    if (!question) {
      question = this.question;
    }
    let reqTemp = req;
    // 只有一个question的ai刷新用的普通ai请求
    if (this.reqData && this.reqData.promptType) {
      req = this.reqData;
    } else if (this.apiType == "stream") {
      if (this.answerType == "questionBank") {
        question = `生成1条类似的文案: ${this.answer}`;
      } else {
      }
      req = Object.assign(
        {
          chatModel: chatModal || config.chatModel,
          options: {
            // conversationId: "41df5b1a-64c2-4c63-ad1f-a9c468943413",
            // parentMessageId: "38c71f2e-2f45-4383-8d25-ec796fb22964"
          },
          temperature: 0.8,
        },
        {
          prompt: question,
        }
      );
    }
    //  else if (!this.freshIsAi && this.reqData) {
    //   // 不是用提示词的方式

    //   req = this.reqData;
    // }

    if (chatStore.id && req.options) {
      req.options.parentMessageId = chatStore.id;
      req.options.conversationId = chatStore.conversationId;
    }

    return new Promise((resolve, reject) => {
      console.log("问ai的reqData", req);
      let reqObj = {
        data: req,
        complete: (res) => {
          debugger;
          console.log("ai类-requesttask-complete");
          // chatStore.completeAnswer();
          this.isLoading = false;

          chatStore.setConversation({
            id: this.id,
            conversationId: this.conversationId,
          });
          this.answerComplete();
          resolve();
          this.scrollToBottom();
        },
        success: () => {
          console.log("ai类-requesttask-success");
        },
      };
      if (this.apiUrl) {
        reqObj.url = this.apiUrl;
      }
      chatStore.updateChat({
        isAi: true,
      });
      this.requestTask = getAiAnswer(reqObj);
      let isFirst = true;
      this.requestTask.onChunkReceived((res) => {
        // return;
        const { lastIndex } = res;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          let aiAnswer = this.handleAiResponse(res);
          let { id, role, conversationId } = aiAnswer;
          this.id = id;
          this.conversationId = conversationId;
          // if (isFirst && !chatStore.conversationId) {
          //   isFirst = false;
          //   chatStore.SetConversation({
          //     id: id,
          //     conversationId: conversationId,
          //   });
          // }
          this.answer = aiAnswer.text;
          let chatData = {
            isAi: true,
            id,
            conversationId,
          };
          role == "THINK"
            ? (chatData.thinkking = aiAnswer.text)
            : (chatData.content = aiAnswer.text);
          // if (role == "ASSISTANT") {
          //   debugger;
          //   chatData.thinkking = aiAnswer.text;
          // } else {
          //   chatData.content  = aiAnswer.text;
          // }
          if (this.extraData) {
            chatData = Object.assign(chatData, this.extraData);
          }
          chatStore.updateChat(chatData);

          // this.handleScollTop();
        }, 100);
      });
    });
  }
  /**
   * @description 题库内容伪装ai回答
   * @param {*} req
   * @returns {Stream} data ai流式回答题库里的内容
   */
  getQuestionBankAiAnswer() {
    console.log("题库内容--ai回答");
    let req = {
      data: {},
    };
    this.reqData ? this.reqData : {};
    // let { question } = param;
    if (this.reqData) {
      req.data = this.reqData;
    } else {
      req.data.question = this.question;
    }
    console.log("发给ai的参数", req);
    req.complete = () => {
      console.log("题库内容--ai回答-complete");
      this.isLoading = false;
      this.answerComplete();
      this.scrollToBottom();
    };
    this.requestTask = getQuestionBankAi(req);
    let timeout = null;
    this.requestTask.onChunkReceived((res) => {
      console.log("onChunkReceived");
      const { lastIndex } = res;
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        let aiAnswer = this.handleAiResponse(res);
        this.answer = aiAnswer.answer;
        chatStore.updateChat({
          content: aiAnswer.answer,
          isAi: true,
        });
      }, 35); // 50
    });
  }
  /**
   * @description 得到题库内容回答返回列表
   * @param {*} param
   * @returns {Array} data 回答列表数组，比如涨粉文案列表
   */
  async getQuestionBankAnswer() {
    console.log("得到题库的回答");
    let param = {};
    param.currentPage = 1;
    param.limit = 3;
    // param.attrStr = id;
    // param.typeName = type.title;
    let res = await getAnswerList({
      params: Object.assign(param, this.reqData),
      apiUrl: this.apiUrl,
    }).then((res) => {
      this.answerComplete();
      chatStore.updateChat({
        content: res.data,
        isAi: true,
      });
      this.scrollToBottom();
      // res.data.forEach((item) => {
      //   chatStore.addChat({
      //     content: item.answer || item.question,
      //     isAi: true,
      //   });
      // });
    });
  }
  Uint8ArrayToString(fileData) {
    let uint8Array = new Uint8Array(fileData);
    let text = "";
    for (let i = 0; i < uint8Array.length; i++) {
      text += String.fromCharCode(uint8Array[i]);
    }
    return text;
  }
  handleAiResponse(chunk) {
    let { data } = chunk;
    let text = this.Uint8ArrayToString(data);
    text = decodeURIComponent(escape(text));
    const lastIndex = text.lastIndexOf("\n", text.length - 2);
    let chunk1 = text;

    if (lastIndex !== -1) {
      chunk1 = text.substring(lastIndex);
    } else {
    }
    let res1 = JSON.parse(chunk1);

    res1.lastIndex = lastIndex;
    return res1;
  }
  scrollToBottom() {
    setTimeout(() => {
      uni.pageScrollTo({
        scrollTop: 999999,
        duration: 0,
      });
    }, 500);
  }
  handleScollTop() {
    return new Promise((resolve) => {
      const query = wx.createSelectorQuery();
      query.select("#content").boundingClientRect();
      query.select(".scroll-view-content").boundingClientRect();
      query.exec((res) => {
        const scrollViewHeight = res[0].height;
        const scrollContentHeight = res[1].height;
        if (scrollContentHeight > scrollViewHeight) {
          const scrollTop = scrollContentHeight - scrollViewHeight;
          this.setData(
            {
              scrollTop,
            },
            () => {
              resolve();
            }
          );
        } else {
          resolve();
        }
      });
    });
  }
  getQuestionBank() {}
}
